package com.arykow.engine.onwebapp.server;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import com.arykow.engine.onwebapp.client.ApplicationService;
import com.arykow.engine.onwebapp.client.Feed;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class ApplicationServiceServlet extends RemoteServiceServlet implements ApplicationService {
	private static final long serialVersionUID = -8638972475035054018L;

	public String greetServer(String input) throws IllegalArgumentException {
		return input;
	}

	static DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
	static Key key = KeyFactory.createKey(ApplicationServiceServlet.class.getName(), ApplicationServiceServlet.class.getName());

	public List<Feed> getFeeds() {
		Query query = new Query(Feed.class.getName(), key);
		List<Feed> result = new ArrayList<Feed>();
		for (Entity entity : datastore.prepare(query).asIterable()) {
			Feed feed = new Feed();
			feed.setId(entity.getKey().getId());
			feed.setTitle(String.class.cast(entity.getProperty("title")));
			feed.setHtmlUrl(String.class.cast(entity.getProperty("htmlUrl")));
			feed.setText(String.class.cast(entity.getProperty("text")));
			feed.setXmlUrl(String.class.cast(entity.getProperty("xmlUrl")));
			result.add(feed);
		}

		Collections.sort(result, new Comparator<Feed>() {
			public int compare(Feed arg0, Feed arg1) {
				String s0 = (arg0 != null && arg0.getTitle() != null) ? arg0.getTitle().toLowerCase() : "";
				String s1 = (arg1 != null && arg1.getTitle() != null) ? arg1.getTitle().toLowerCase() : "";
				return s0.compareTo(s1);
			}
		});
		return result;
	}

	public Long addFeed(final String xmlUrl) {
		class Result {
			Long value;
		}

		final Result result = new Result();
		if (xmlUrl != null) {
			for (Entity entity : datastore.prepare(new Query(Feed.class.getName(), key)).asIterable()) {
				long id = entity.getKey().getId();
				if (xmlUrl.equalsIgnoreCase(String.class.cast(entity.getProperty("xmlUrl")))) {
					result.value = id;
					break;
				}
			}
		}

		if (result.value == null) {
			FeedParser feedParser = new FeedParser();
			FeedParserListener listener = new FeedParserListener() {
				Entity entity = createFeedEntity();

				public void listenStop() {
					Key key = persistFeedEntity(entity);
					result.value = key.getId();
				}

				public void listenStart(String title, String link, int size) {
					updateFeedEntity(entity, xmlUrl, title, link);
				}

				public void listenEntry(int index, String id, String title, String description, String link, Date publishedDate) {
				}
			};
			try {
				feedParser.parse(xmlUrl, listener);
			} catch (Exception e) {
			}
		}

		return result.value;
	}

	public static Key persistFeedEntity(Entity entity) {
		Key key = null;
		for (Entity ee : datastore.prepare(new Query(Feed.class.getName(), key)).asIterable()) {
			if (String.class.cast(ee.getProperty("xmlUrl")).equalsIgnoreCase(String.class.cast(entity.getProperty("xmlUrl")))) {
				key = ee.getKey();
				break;
			}
		}
		if (key == null) {
			datastore.put(entity);
		}

		return key;
	}

	public static void updateFeedEntity(Entity entity, final String xmlUrl, String title, String link) {
		entity.setProperty("text", title);
		entity.setProperty("title", title);
		entity.setProperty("xmlUrl", xmlUrl);
		entity.setProperty("htmlUrl", link);
	}

	public static Entity createFeedEntity() {
		Entity entity = new Entity(Feed.class.getName(), key);
		return entity;
	}

	@Override
	public Feed getFeed(long feedId) {
		Feed result = null;
		for (Entity entity : datastore.prepare(new Query(Feed.class.getName(), key)).asIterable()) {
			long id = entity.getKey().getId();
			if (id == feedId) {
				Feed feed = new Feed();
				feed.setId(id);
				feed.setTitle(String.class.cast(entity.getProperty("title")));
				feed.setHtmlUrl(String.class.cast(entity.getProperty("htmlUrl")));
				feed.setText(String.class.cast(entity.getProperty("text")));
				feed.setXmlUrl(String.class.cast(entity.getProperty("xmlUrl")));
				result = feed;
				break;
			}
		}
		return result;
	}
}
